import tkinter as tk
from tkinter import colorchooser, filedialog, messagebox
import os
import base64
from io import BytesIO
from PIL import Image, ImageDraw, ImageTk, ImageColor

class DrawingApp:
    def __init__(self, root):
        self.root = root
        self.root.title("简易画图板")
        self.root.geometry("1000x600")
        self.root.configure(bg="#f0f0f0")
        
        # 设置应用图标
        try:
            if os.path.exists("resources/icon.ico"):
                self.root.iconbitmap("resources/icon.ico")
        except:
            pass
        
        # 初始化变量
        self.setup_variables()
        
        # 创建UI组件
        self.create_widgets()
        
        # 绑定事件
        self.bind_events()
        
    def setup_variables(self):
        # 画布尺寸
        self.canvas_width = 800
        self.canvas_height = 500
        
        # 绘图相关变量
        self.prev_x = None
        self.prev_y = None
        self.drawing_tool = "pencil"
        self.color = "#000000"  # 默认黑色
        self.line_width = 2
        
        # 缩放相关变量
        self.scale_factor = 1.0  # 初始缩放比例为1.0
        self.min_scale = 0.1    # 最小缩放比例
        self.max_scale = 5.0    # 最大缩放比例
        self.scale_step = 0.1   # 缩放步长
        
        # 画布平移相关变量
        self.pan_x = 0          # 水平平移量
        self.pan_y = 0          # 垂直平移量
        self.pan_start_x = 0    # 平移起始点X
        self.pan_start_y = 0    # 平移起始点Y
        
        # 刻度尺相关变量
        self.ruler_size = 20     # 刻度尺宽度
        self.ruler_unit = 50     # 主刻度单位（像素）
        self.ruler_subunit = 10  # 次刻度单位（像素）
        self.show_rulers = True  # 是否显示刻度尺
        
        # 创建空白图像
        self.image = Image.new("RGB", (self.canvas_width, self.canvas_height), "white")
        self.draw = ImageDraw.Draw(self.image)
        
        # 保存操作历史用于撤销
        self.history = []
        self.history_index = -1
        self.save_history()
    
    # 创建简单的工具图标
    def create_tool_icons(self):
        # 创建图标字典
        icons = {}
        size = (24, 24)  # 增大图标尺寸
        
        # 铅笔图标 - 简单的黑色对角线
        pencil_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(pencil_img)
        draw.line([(4, 4), (20, 20)], fill="black", width=2)
        # 添加一些细节使图标更像铅笔
        draw.line([(4, 4), (8, 4)], fill="black", width=2)  # 铅笔顶部
        draw.line([(4, 4), (4, 8)], fill="black", width=2)  # 铅笔侧面
        self.pencil_icon = ImageTk.PhotoImage(pencil_img)  # 保存到实例变量
        icons["pencil"] = self.pencil_icon
        
        # 直线图标 - 水平线
        line_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(line_img)
        draw.line([(4, 12), (20, 12)], fill="black", width=2)
        self.line_icon = ImageTk.PhotoImage(line_img)  # 保存到实例变量
        icons["line"] = self.line_icon
        
        # 矩形图标 - 空心矩形
        rect_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(rect_img)
        draw.rectangle([(4, 4), (20, 20)], outline="black", width=2)
        self.rectangle_icon = ImageTk.PhotoImage(rect_img)  # 保存到实例变量
        icons["rectangle"] = self.rectangle_icon
        
        # 圆形图标 - 空心圆形
        oval_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(oval_img)
        draw.ellipse([(4, 4), (20, 20)], outline="black", width=2)
        self.oval_icon = ImageTk.PhotoImage(oval_img)  # 保存到实例变量
        icons["oval"] = self.oval_icon
        
        # 填充图标 - 填充的小矩形
        fill_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(fill_img)
        draw.rectangle([(6, 6), (18, 18)], fill="black")
        self.fill_icon = ImageTk.PhotoImage(fill_img)  # 保存到实例变量
        icons["fill"] = self.fill_icon
        
        # 橡皮擦图标 - 白色矩形
        eraser_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(eraser_img)
        draw.rectangle([(4, 4), (20, 20)], fill="white", outline="black", width=2)
        self.eraser_icon = ImageTk.PhotoImage(eraser_img)  # 保存到实例变量
        icons["eraser"] = self.eraser_icon
        
        # 文本图标 - 字母"T"
        text_img = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(text_img)
        draw.line([(6, 6), (18, 6)], fill="black", width=2)  # 顶部横线
        draw.line([(12, 6), (12, 18)], fill="black", width=2)  # 竖线
        self.text_icon = ImageTk.PhotoImage(text_img)  # 保存到实例变量
        icons["text"] = self.text_icon
        
        return icons
    
    def create_widgets(self):
        # 主框架
        main_frame = tk.Frame(self.root, bg="#f0f0f0")
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 工具栏框架
        toolbar_frame = tk.Frame(main_frame, bg="#e0e0e0", bd=2, relief=tk.RAISED)
        toolbar_frame.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5)
        
        # 获取工具图标
        self.tool_icons = self.create_tool_icons()
        
        # 工具按钮
        tools = [
            ("铅笔", "pencil", "#1"),
            ("直线", "line", "#2"),
            ("矩形", "rectangle", "#3"),
            ("圆形", "oval", "#4"),
            ("填充", "fill", "#5"),
            ("橡皮擦", "eraser", "#6"),
            ("文本", "text", "#7")
        ]
        
        # 工具标签
        tk.Label(toolbar_frame, text="绘图工具", bg="#e0e0e0", font=("Arial", 10, "bold")).pack(pady=5)
        
        # 创建工具按钮
        self.tool_buttons = {}
        for text, tool, shortcut in tools:
            btn = tk.Button(
                toolbar_frame, 
                text=f"{text} {shortcut}", 
                width=10,
                height=2,
                command=lambda t=tool: self.set_tool(t)
            )
            btn.pack(pady=2)
            self.tool_buttons[tool] = btn
        
        # 设置默认选中的工具
        self.tool_buttons["pencil"].config(relief=tk.SUNKEN, bg="#c0c0c0")
        
        # 颜色选择按钮
        tk.Label(toolbar_frame, text="颜色", bg="#e0e0e0", font=("Arial", 10, "bold")).pack(pady=5)
        self.color_button = tk.Button(
            toolbar_frame, 
            bg=self.color, 
            width=10, 
            height=1,
            command=self.choose_color
        )
        self.color_button.pack(pady=2)
        
        # 线宽选择
        tk.Label(toolbar_frame, text="线宽", bg="#e0e0e0", font=("Arial", 10, "bold")).pack(pady=5)
        widths = [1, 2, 3, 5, 8, 12]
        width_frame = tk.Frame(toolbar_frame, bg="#e0e0e0")
        width_frame.pack(pady=2)
        
        self.width_buttons = {}
        for width in widths:
            btn = tk.Button(
                width_frame,
                text=str(width),
                width=2,
                command=lambda w=width: self.set_line_width(w)
            )
            btn.pack(side=tk.LEFT, padx=1)
            self.width_buttons[width] = btn
        
        # 设置默认线宽按钮
        self.width_buttons[2].config(relief=tk.SUNKEN, bg="#c0c0c0")
        
        # 操作按钮
        tk.Label(toolbar_frame, text="操作", bg="#e0e0e0", font=("Arial", 10, "bold")).pack(pady=5)
        operations = [
            ("清空", self.clear_canvas, "Ctrl+N"),
            ("撤销", self.undo, "Ctrl+Z"),
            ("重做", self.redo, "Ctrl+Y"),
            ("保存", self.save_image, "Ctrl+S"),
            ("打开", self.open_image, "Ctrl+O")
        ]
        
        for text, command, shortcut in operations:
            btn = tk.Button(
                toolbar_frame,
                text=f"{text} ({shortcut})",
                width=15,
                command=command
            )
            btn.pack(pady=2)
            
        # 缩放控制
        tk.Label(toolbar_frame, text="缩放控制", bg="#e0e0e0", font=("Arial", 10, "bold")).pack(pady=5)
        
        # 缩放比例显示
        scale_frame = tk.Frame(toolbar_frame, bg="#e0e0e0")
        scale_frame.pack(pady=2, fill=tk.X)
        
        self.scale_label = tk.Label(scale_frame, text="100%", width=6, bg="#e0e0e0")
        self.scale_label.pack(side=tk.LEFT, padx=2)
        
        # 缩放按钮
        zoom_frame = tk.Frame(toolbar_frame, bg="#e0e0e0")
        zoom_frame.pack(pady=2, fill=tk.X)
        
        zoom_in_btn = tk.Button(zoom_frame, text="放大", width=7, command=self.zoom_in)
        zoom_in_btn.pack(side=tk.LEFT, padx=2)
        
        zoom_out_btn = tk.Button(zoom_frame, text="缩小", width=7, command=self.zoom_out)
        zoom_out_btn.pack(side=tk.LEFT, padx=2)
        
        # 重置缩放按钮
        reset_zoom_btn = tk.Button(toolbar_frame, text="重置缩放 (100%)", width=15, command=self.reset_zoom)
        reset_zoom_btn.pack(pady=2)
        
        # 刻度尺开关
        self.ruler_var = tk.BooleanVar(value=self.show_rulers)
        ruler_check = tk.Checkbutton(
            toolbar_frame, 
            text="显示刻度尺", 
            variable=self.ruler_var,
            onvalue=True, 
            offvalue=False,
            bg="#e0e0e0",
            command=self.toggle_rulers
        )
        ruler_check.pack(pady=2)
        
        # 画布主框架
        self.canvas_main_frame = tk.Frame(main_frame, bg="#d0d0d0", bd=2, relief=tk.SUNKEN)
        self.canvas_main_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建角落空白区域（左上角）
        self.corner_canvas = tk.Canvas(
            self.canvas_main_frame,
            width=self.ruler_size,
            height=self.ruler_size,
            bg="#d0d0d0",
            highlightthickness=0
        )
        self.corner_canvas.grid(row=0, column=0, sticky="nsew")
        
        # 创建水平刻度尺（顶部）
        self.h_ruler = tk.Canvas(
            self.canvas_main_frame,
            height=self.ruler_size,
            bg="#d0d0d0",
            highlightthickness=0
        )
        self.h_ruler.grid(row=0, column=1, sticky="ew")
        
        # 创建垂直刻度尺（左侧）
        self.v_ruler = tk.Canvas(
            self.canvas_main_frame,
            width=self.ruler_size,
            bg="#d0d0d0",
            highlightthickness=0
        )
        self.v_ruler.grid(row=1, column=0, sticky="ns")
        
        # 创建画布框架（带滚动条）
        canvas_frame = tk.Frame(self.canvas_main_frame, bg="white")
        canvas_frame.grid(row=1, column=1, sticky="nsew")
        
        # 设置网格权重，使画布区域可以扩展
        self.canvas_main_frame.grid_rowconfigure(1, weight=1)
        self.canvas_main_frame.grid_columnconfigure(1, weight=1)
        
        # 创建水平滚动条
        h_scrollbar = tk.Scrollbar(canvas_frame, orient=tk.HORIZONTAL)
        h_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 创建垂直滚动条
        v_scrollbar = tk.Scrollbar(canvas_frame, orient=tk.VERTICAL)
        v_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建画布
        self.canvas = tk.Canvas(
            canvas_frame,
            width=self.canvas_width,
            height=self.canvas_height,
            bg="white",
            highlightthickness=0,
            xscrollcommand=h_scrollbar.set,
            yscrollcommand=v_scrollbar.set
        )
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 配置滚动条
        h_scrollbar.config(command=self.canvas.xview)
        v_scrollbar.config(command=self.canvas.yview)
        
        # 显示初始空白图像
        self.update_canvas()
        
        # 绘制刻度尺
        self.draw_rulers()
        
        # 状态栏
        self.status_bar = tk.Label(
            self.root, 
            text="就绪 | 工具: 铅笔 | 颜色: 黑色 | 线宽: 2", 
            bd=1, 
            relief=tk.SUNKEN, 
            anchor=tk.W
        )
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
    
    def bind_events(self):
        # 鼠标事件
        self.canvas.bind("<Button-1>", self.on_mouse_down)
        self.canvas.bind("<B1-Motion>", self.on_mouse_move)
        self.canvas.bind("<ButtonRelease-1>", self.on_mouse_up)
        
        # 鼠标滚轮缩放
        self.canvas.bind("<Control-MouseWheel>", self.on_mouse_wheel)
        
        # 按住Ctrl+左键拖动画布
        self.canvas.bind("<Control-Button-1>", self.on_pan_start)
        self.canvas.bind("<Control-B1-Motion>", self.on_pan_move)
        
        # 键盘快捷键
        self.root.bind("<Control-z>", lambda event: self.undo())
        self.root.bind("<Control-y>", lambda event: self.redo())
        self.root.bind("<Control-s>", lambda event: self.save_image())
        self.root.bind("<Control-o>", lambda event: self.open_image())
        self.root.bind("<Control-n>", lambda event: self.clear_canvas())
        
        # 数字键快捷键选择工具
        self.root.bind("1", lambda event: self.set_tool("pencil"))
        self.root.bind("2", lambda event: self.set_tool("line"))
        self.root.bind("3", lambda event: self.set_tool("rectangle"))
        self.root.bind("4", lambda event: self.set_tool("oval"))
        self.root.bind("5", lambda event: self.set_tool("eraser"))
        self.root.bind("6", lambda event: self.set_tool("text"))
    
    def set_tool(self, tool):
        # 重置所有工具按钮
        for btn in self.tool_buttons.values():
            btn.config(relief=tk.RAISED, bg="SystemButtonFace")
        
        # 设置选中的工具按钮
        self.tool_buttons[tool].config(relief=tk.SUNKEN, bg="#c0c0c0")
        self.drawing_tool = tool
        
        # 更新状态栏
        self.update_status()
    
    def set_line_width(self, width):
        # 重置所有线宽按钮
        for btn in self.width_buttons.values():
            btn.config(relief=tk.RAISED, bg="SystemButtonFace")
        
        # 设置选中的线宽按钮
        self.width_buttons[width].config(relief=tk.SUNKEN, bg="#c0c0c0")
        self.line_width = width
        
        # 更新状态栏
        self.update_status()
    
    def choose_color(self):
        color = colorchooser.askcolor(initialcolor=self.color)[1]
        if color:
            self.color = color
            self.color_button.config(bg=color)
            self.update_status()
    
    def update_status(self):
        tool_names = {
            "pencil": "铅笔",
            "line": "直线",
            "rectangle": "矩形",
            "oval": "圆形",
            "eraser": "橡皮擦",
            "text": "文本"
        }
        
        color_name = "自定义"
        if self.color == "#000000":
            color_name = "黑色"
        elif self.color == "#FFFFFF":
            color_name = "白色"
        elif self.color == "#FF0000":
            color_name = "红色"
        elif self.color == "#00FF00":
            color_name = "绿色"
        elif self.color == "#0000FF":
            color_name = "蓝色"
        
        self.status_bar.config(
            text=f"就绪 | 工具: {tool_names.get(self.drawing_tool, self.drawing_tool)} | "
                 f"颜色: {color_name} | 线宽: {self.line_width}"
        )
    
    def on_mouse_down(self, event):
        # 获取鼠标在画布上的实际位置（考虑缩放和平移）
        canvas_x = (event.x - self.pan_x) / self.scale_factor
        canvas_y = (event.y - self.pan_y) / self.scale_factor
        
        self.prev_x = canvas_x
        self.prev_y = canvas_y
        
        # 如果是形状工具，记录起始点
        if self.drawing_tool in ["line", "rectangle", "oval", "fill"]:
            self.start_x = canvas_x
            self.start_y = canvas_y
            # 创建临时形状
            self.temp_item = None
            
            # 如果是填充工具，立即执行填充
            if self.drawing_tool == "fill":
                # 获取点击位置的颜色
                try:
                    # 确保坐标在图像范围内
                    if 0 <= int(canvas_x) < self.canvas_width and 0 <= int(canvas_y) < self.canvas_height:
                        self.flood_fill(int(canvas_x), int(canvas_y))
                        self.update_canvas()
                        self.save_history()
                except Exception as e:
                    print(f"填充错误: {e}")
        
        # 如果是文本工具，弹出输入对话框
        elif self.drawing_tool == "text":
            self.add_text(int(canvas_x), int(canvas_y))
    
    def on_mouse_move(self, event):
        # 获取鼠标在画布上的实际位置（考虑缩放和平移）
        canvas_x = (event.x - self.pan_x) / self.scale_factor
        canvas_y = (event.y - self.pan_y) / self.scale_factor
        
        if self.drawing_tool == "pencil":
            # 绘制铅笔线条
            if self.prev_x and self.prev_y:
                self.draw.line(
                    [(self.prev_x, self.prev_y), (canvas_x, canvas_y)],
                    fill=self.color,
                    width=self.line_width
                )
                self.update_canvas()
        
        elif self.drawing_tool == "eraser":
            # 绘制橡皮擦（白色线条）
            if self.prev_x and self.prev_y:
                self.draw.line(
                    [(self.prev_x, self.prev_y), (canvas_x, canvas_y)],
                    fill="white",
                    width=self.line_width * 2  # 橡皮擦稍大一些
                )
                self.update_canvas()
        
        elif self.drawing_tool in ["line", "rectangle", "oval"]:
            # 更新临时形状
            if self.temp_item:
                self.canvas.delete(self.temp_item)
            
            # 计算屏幕上的坐标（考虑缩放和平移）
            screen_start_x = self.start_x * self.scale_factor + self.pan_x
            screen_start_y = self.start_y * self.scale_factor + self.pan_y
            screen_x = event.x
            screen_y = event.y
            
            if self.drawing_tool == "line":
                self.temp_item = self.canvas.create_line(
                    screen_start_x, screen_start_y, screen_x, screen_y,
                    fill=self.color,
                    width=self.line_width
                )
            elif self.drawing_tool == "rectangle":
                # 确保坐标点顺序正确（左上角和右下角）
                x0 = min(screen_start_x, screen_x)
                y0 = min(screen_start_y, screen_y)
                x1 = max(screen_start_x, screen_x)
                y1 = max(screen_start_y, screen_y)
                # 检查是否按下了Shift键（填充模式）
                if event.state & 0x1:  # Shift键被按下
                    self.temp_item = self.canvas.create_rectangle(
                        x0, y0, x1, y1,
                        outline=self.color,
                        fill=self.color,
                        width=self.line_width
                    )
                else:
                    self.temp_item = self.canvas.create_rectangle(
                        x0, y0, x1, y1,
                        outline=self.color,
                        width=self.line_width
                    )
            elif self.drawing_tool == "oval":
                # 确保坐标点顺序正确（左上角和右下角）
                x0 = min(screen_start_x, screen_x)
                y0 = min(screen_start_y, screen_y)
                x1 = max(screen_start_x, screen_x)
                y1 = max(screen_start_y, screen_y)
                # 检查是否按下了Shift键（填充模式）
                if event.state & 0x1:  # Shift键被按下
                    self.temp_item = self.canvas.create_oval(
                        x0, y0, x1, y1,
                        outline=self.color,
                        fill=self.color,
                        width=self.line_width
                    )
                else:
                    self.temp_item = self.canvas.create_oval(
                        x0, y0, x1, y1,
                        outline=self.color,
                        width=self.line_width
                    )
        
        self.prev_x = x
        self.prev_y = y
    
    def on_mouse_up(self, event):
        # 获取鼠标在画布上的实际位置（考虑缩放和平移）
        canvas_x = (event.x - self.pan_x) / self.scale_factor
        canvas_y = (event.y - self.pan_y) / self.scale_factor
        
        if self.drawing_tool in ["line", "rectangle", "oval"]:
            # 删除临时形状
            if self.temp_item:
                self.canvas.delete(self.temp_item)
            
            # 在图像上绘制最终形状
            if self.drawing_tool == "line":
                self.draw.line(
                    [(int(self.start_x), int(self.start_y)), (int(canvas_x), int(canvas_y))],
                    fill=self.color,
                    width=self.line_width
                )
            elif self.drawing_tool == "rectangle":
                # 确保坐标点顺序正确（左上角和右下角）
                x0 = min(int(self.start_x), int(canvas_x))
                y0 = min(int(self.start_y), int(canvas_y))
                x1 = max(int(self.start_x), int(canvas_x))
                y1 = max(int(self.start_y), int(canvas_y))
                
                # 检查是否按下了Shift键（填充模式）
                if event.state & 0x1:  # Shift键被按下
                    self.draw.rectangle(
                        [(x0, y0), (x1, y1)],
                        outline=self.color,
                        fill=self.color,
                        width=self.line_width
                    )
                else:
                    self.draw.rectangle(
                        [(x0, y0), (x1, y1)],
                        outline=self.color,
                        width=self.line_width
                    )
            elif self.drawing_tool == "oval":
                # 确保坐标点顺序正确（左上角和右下角）
                x0 = min(int(self.start_x), int(canvas_x))
                y0 = min(int(self.start_y), int(canvas_y))
                x1 = max(int(self.start_x), int(canvas_x))
                y1 = max(int(self.start_y), int(canvas_y))
                
                # 检查是否按下了Shift键（填充模式）
                if event.state & 0x1:  # Shift键被按下
                    self.draw.ellipse(
                        [(x0, y0), (x1, y1)],
                        outline=self.color,
                        fill=self.color,
                        width=self.line_width
                    )
                else:
                    self.draw.ellipse(
                        [(x0, y0), (x1, y1)],
                        outline=self.color,
                        width=self.line_width
                    )
            
            self.update_canvas()
            self.save_history()
        
        elif self.drawing_tool in ["pencil", "eraser"]:
            # 保存历史记录
            self.save_history()
        
        # 重置坐标
        self.prev_x = None
        self.prev_y = None
        
    def flood_fill(self, x, y):
        """填充算法实现"""
        # 获取目标颜色（点击位置的颜色）
        target_color = self.image.getpixel((x, y))
        
        # 如果目标颜色与填充颜色相同，则不需要填充
        fill_color = ImageColor.getrgb(self.color)
        if target_color == fill_color:
            return
        
        # 使用队列实现填充
        from collections import deque
        queue = deque([(x, y)])
        width, height = self.image.size
        
        # 访问过的像素点
        visited = set()
        
        while queue:
            cx, cy = queue.popleft()
            
            # 如果超出边界或已访问过或颜色不匹配，则跳过
            if (cx < 0 or cx >= width or cy < 0 or cy >= height or 
                (cx, cy) in visited or self.image.getpixel((cx, cy)) != target_color):
                continue
            
            # 设置颜色并标记为已访问
            self.image.putpixel((cx, cy), fill_color)
            visited.add((cx, cy))
            
            # 将相邻像素加入队列
            queue.append((cx + 1, cy))
            queue.append((cx - 1, cy))
            queue.append((cx, cy + 1))
            queue.append((cx, cy - 1))
    
    def add_text(self, x, y):
        # 弹出文本输入对话框
        text = tk.simpledialog.askstring("添加文本", "请输入文本:")
        if text:
            # 在图像上绘制文本
            from PIL import ImageFont
            try:
                font = ImageFont.truetype("simhei.ttf", 20)  # 尝试使用黑体
            except IOError:
                font = ImageFont.load_default()
            
            self.draw.text((x, y), text, fill=self.color, font=font)
            self.update_canvas()
            self.save_history()
    
    def update_canvas(self):
        # 根据缩放比例调整图像大小
        # 计算缩放后的尺寸
        scaled_width = int(self.canvas_width * self.scale_factor)
        scaled_height = int(self.canvas_height * self.scale_factor)
        
        if self.scale_factor != 1.0:
            # 缩放图像
            scaled_image = self.image.resize((scaled_width, scaled_height), Image.LANCZOS)
            self.tk_image = ImageTk.PhotoImage(scaled_image)
        else:
            # 不缩放，直接使用原始图像
            self.tk_image = ImageTk.PhotoImage(self.image)
        
        # 清除画布并显示更新后的图像，应用平移偏移
        self.canvas.delete("all")
        self.canvas.create_image(self.pan_x, self.pan_y, anchor=tk.NW, image=self.tk_image)
        
        # 计算滚动区域大小
        # 当缩放比例小于1时，需要更大的滚动区域
        if self.scale_factor < 1.0:
            # 计算实际需要的绘图区域大小
            actual_width = max(self.canvas_width / self.scale_factor, self.canvas.winfo_width())
            actual_height = max(self.canvas_height / self.scale_factor, self.canvas.winfo_height())
            
            # 设置滚动区域为实际需要的大小加上平移偏移
            self.canvas.config(scrollregion=(0, 0, 
                                             actual_width + abs(self.pan_x), 
                                             actual_height + abs(self.pan_y)))
        else:
            # 当缩放比例大于等于1时，使用原来的逻辑
            self.canvas.config(scrollregion=(0, 0, 
                                             max(self.canvas.winfo_width(), scaled_width + self.pan_x), 
                                             max(self.canvas.winfo_height(), scaled_height + self.pan_y)))
        
        # 更新刻度尺
        self.draw_rulers()
        
    def draw_rulers(self):
        """绘制水平和垂直刻度尺"""
        if not self.show_rulers:
            self.h_ruler.delete("all")
            self.v_ruler.delete("all")
            self.corner_canvas.delete("all")
            return
        
        # 清除现有刻度尺
        self.h_ruler.delete("all")
        self.v_ruler.delete("all")
        self.corner_canvas.delete("all")
        
        # 获取画布可见区域的大小
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        
        # 调整刻度尺大小以匹配画布
        self.h_ruler.config(width=canvas_width)
        self.v_ruler.config(height=canvas_height)
        
        # 绘制角落方块
        self.corner_canvas.create_rectangle(
            0, 0, self.ruler_size, self.ruler_size, 
            fill="#d0d0d0", outline="#a0a0a0"
        )
        
        # 计算缩放后的刻度单位
        scaled_unit = self.ruler_unit * self.scale_factor
        scaled_subunit = self.ruler_subunit * self.scale_factor
        
        # 绘制水平刻度尺
        for i in range(0, int(canvas_width / scaled_subunit) + 1):
            x = i * scaled_subunit
            if i % (self.ruler_unit // self.ruler_subunit) == 0:
                # 主刻度
                self.h_ruler.create_line(x, self.ruler_size, x, 0, fill="#505050")
                # 刻度标签
                pixel_pos = int(i * self.ruler_subunit)  # 实际像素位置
                self.h_ruler.create_text(x, 10, text=str(pixel_pos), font=("Arial", 7))
            else:
                # 次刻度
                self.h_ruler.create_line(x, self.ruler_size, x, self.ruler_size//2, fill="#505050")
        
        # 绘制垂直刻度尺
        for i in range(0, int(canvas_height / scaled_subunit) + 1):
            y = i * scaled_subunit
            if i % (self.ruler_unit // self.ruler_subunit) == 0:
                # 主刻度
                self.v_ruler.create_line(self.ruler_size, y, 0, y, fill="#505050")
                # 刻度标签
                pixel_pos = int(i * self.ruler_subunit)  # 实际像素位置
                self.v_ruler.create_text(10, y, text=str(pixel_pos), font=("Arial", 7))
            else:
                # 次刻度
                self.v_ruler.create_line(self.ruler_size, y, self.ruler_size//2, y, fill="#505050")
    
    def zoom_in(self):
        """放大画布"""
        if self.scale_factor < self.max_scale:
            self.scale_factor += self.scale_step
            self.scale_factor = min(self.scale_factor, self.max_scale)  # 确保不超过最大缩放比例
            self.update_scale_display()
            self.update_canvas()
    
    def zoom_out(self):
        """缩小画布"""
        if self.scale_factor > self.min_scale:
            self.scale_factor -= self.scale_step
            self.scale_factor = max(self.scale_factor, self.min_scale)  # 确保不低于最小缩放比例
            self.update_scale_display()
            self.update_canvas()
    
    def reset_zoom(self):
        """重置缩放比例为100%"""
        self.scale_factor = 1.0
        self.update_scale_display()
        self.update_canvas()
    
    def update_scale_display(self):
        """更新缩放比例显示"""
        percentage = int(self.scale_factor * 100)
        self.scale_label.config(text=f"{percentage}%")
        
        # 更新状态栏
        self.update_status()
    
    def toggle_rulers(self):
        """切换刻度尺显示状态"""
        self.show_rulers = self.ruler_var.get()
        
        # 调整画布框架布局
        if self.show_rulers:
            # 显示刻度尺
            self.corner_canvas.grid(row=0, column=0, sticky="nsew")
            self.h_ruler.grid(row=0, column=1, sticky="ew")
            self.v_ruler.grid(row=1, column=0, sticky="ns")
        else:
            # 隐藏刻度尺
            self.corner_canvas.grid_remove()
            self.h_ruler.grid_remove()
            self.v_ruler.grid_remove()
        
        # 更新刻度尺
        self.draw_rulers()
    
    def on_mouse_wheel(self, event):
        """处理鼠标滚轮事件，用于缩放画布"""
        # 获取鼠标位置
        x, y = event.x, event.y
        
        # 根据滚轮方向确定缩放方向
        # Windows系统中，event.delta为正表示向上滚动（放大），为负表示向下滚动（缩小）
        if event.delta > 0:
            # 放大
            if self.scale_factor < self.max_scale:
                self.scale_factor += self.scale_step
                self.scale_factor = min(self.scale_factor, self.max_scale)
        else:
            # 缩小
            if self.scale_factor > self.min_scale:
                self.scale_factor -= self.scale_step
                self.scale_factor = max(self.scale_factor, self.min_scale)
        
        # 更新缩放比例显示
        self.update_scale_display()
        
        # 更新画布
        self.update_canvas()
    
    def on_pan_start(self, event):
        """开始画布拖动"""
        # 记录拖动起始点
        self.pan_start_x = event.x - self.pan_x
        self.pan_start_y = event.y - self.pan_y
        
        # 改变鼠标指针形状
        self.canvas.config(cursor="fleur")
    
    def on_pan_move(self, event):
        """拖动画布"""
        # 计算新的平移量
        self.pan_x = event.x - self.pan_start_x
        self.pan_y = event.y - self.pan_start_y
        
        # 更新画布
        self.update_canvas()
        
        # 松开Ctrl键时恢复默认鼠标指针
        self.canvas.bind("<KeyRelease-Control_L>", lambda e: self.canvas.config(cursor=""))
        self.canvas.bind("<KeyRelease-Control_R>", lambda e: self.canvas.config(cursor=""))
    
    def save_history(self):
        # 保存当前图像状态到历史记录
        if self.history_index < len(self.history) - 1:
            # 如果在历史中间进行了新操作，删除后面的历史
            self.history = self.history[:self.history_index + 1]
        
        # 创建当前图像的副本并添加到历史记录
        self.history.append(self.image.copy())
        self.history_index = len(self.history) - 1
        
        # 限制历史记录长度，防止内存占用过大
        max_history = 20
        if len(self.history) > max_history:
            self.history = self.history[-max_history:]
            self.history_index = len(self.history) - 1
    
    def undo(self):
        if self.history_index > 0:
            self.history_index -= 1
            self.image = self.history[self.history_index].copy()
            self.draw = ImageDraw.Draw(self.image)
            self.update_canvas()
    
    def redo(self):
        if self.history_index < len(self.history) - 1:
            self.history_index += 1
            self.image = self.history[self.history_index].copy()
            self.draw = ImageDraw.Draw(self.image)
            self.update_canvas()
    
    def clear_canvas(self):
        # 确认对话框
        if messagebox.askyesno("确认", "确定要清空画布吗？"):
            # 创建新的空白图像
            self.image = Image.new("RGB", (self.canvas_width, self.canvas_height), "white")
            self.draw = ImageDraw.Draw(self.image)
            self.update_canvas()
            self.save_history()
    
    def save_image(self):
        # 打开文件对话框
        file_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[
                ("PNG文件", "*.png"),
                ("JPEG文件", "*.jpg;*.jpeg"),
                ("所有文件", "*.*")
            ]
        )
        
        if file_path:
            try:
                self.image.save(file_path)
                messagebox.showinfo("成功", f"图像已保存到: {file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"保存图像时出错: {str(e)}")
    
    def open_image(self):
        # 打开文件对话框
        file_path = filedialog.askopenfilename(
            filetypes=[
                ("图像文件", "*.png;*.jpg;*.jpeg;*.bmp;*.gif"),
                ("所有文件", "*.*")
            ]
        )
        
        if file_path:
            try:
                # 打开图像
                opened_image = Image.open(file_path)
                
                # 调整图像大小以适应画布
                if opened_image.width > self.canvas_width or opened_image.height > self.canvas_height:
                    opened_image = opened_image.resize(
                        (self.canvas_width, self.canvas_height),
                        Image.LANCZOS
                    )
                
                # 创建新的白色背景图像
                self.image = Image.new("RGB", (self.canvas_width, self.canvas_height), "white")
                
                # 将打开的图像粘贴到中心位置
                paste_x = (self.canvas_width - opened_image.width) // 2
                paste_y = (self.canvas_height - opened_image.height) // 2
                self.image.paste(opened_image, (paste_x, paste_y))
                
                # 更新绘图对象和画布
                self.draw = ImageDraw.Draw(self.image)
                self.update_canvas()
                self.save_history()
                
                messagebox.showinfo("成功", f"已打开图像: {file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"打开图像时出错: {str(e)}")

# 主程序入口
if __name__ == "__main__":
    root = tk.Tk()
    app = DrawingApp(root)
    root.mainloop()